package net.svenbuschbeck.gwt.ao.client;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

public class ActiveClippedList<T> extends ActiveList<T> {

	private List<T> allObjects;
	private int startIndex;
	private int endIndex;

	public ActiveClippedList(Collection<T> allObjects) {
		this(allObjects, false, false);
	}

	public ActiveClippedList(boolean valuesHaveToBeUnique) {
		this(valuesHaveToBeUnique, false);
	}

	public ActiveClippedList(boolean valuesHaveToBeUnique, boolean valuesCanBeNull) {
		this(null, valuesHaveToBeUnique, valuesCanBeNull);
	}

	public ActiveClippedList(Collection<T> allObjects, boolean valuesHaveToBeUnique, boolean valuesCanBeNull) {
		super(valuesHaveToBeUnique, valuesCanBeNull);
		adopt(allObjects);
	}

	/**
	 * Events will be triggered - trickerValueAddedEventForAll will be ignored.
	 */
	@Override public void adopt(Collection<T> adoptCollection, boolean trickerValueAddedEventForAll) {
		adopt(adoptCollection);
	}

	public void adopt(Collection<T> adoptCollection) {
		// transform allObjects into a list or create an empty list if allObjects is null
		this.allObjects = (adoptCollection == null) ? new LinkedList<T>()
			: ((adoptCollection instanceof List<?>) ? (List<T>) adoptCollection : new LinkedList<T>(adoptCollection));
		applyClipping();
	}

	public void setClipping(int startIndex, int endIndex) {
		this.startIndex = startIndex;
		this.endIndex = endIndex;
		assert startIndex <= endIndex : "showObjects: endIndex > startIndex";
		assert startIndex >= 0 : "showObjects: startIndex < 0";
		assert endIndex >= 0 : "showObjects: endIndex < 0";
		applyClipping();
	}

	private void applyClipping() {
		boolean shouldBeVisible;
		T mediumStub;
		for (int x = 0; x < allObjects.size(); x++) {
			shouldBeVisible = startIndex <= x && x < endIndex;
			mediumStub = allObjects.get(x);
			if (contains(mediumStub)) {
				if (!shouldBeVisible) {
					remove(mediumStub);
				}
			} else {
				if (shouldBeVisible) {
					add(mediumStub);
				}
			}
		}
	}

	public int getClippingStartIndex() {
		return startIndex;
	}

	public int getClippinEndIndex() {
		return endIndex;
	}

	public Collection<T> getAllObjects() {
		return allObjects;
	}

}
